<template>
  <picker :range="newRange" :range-key="props.rangeKey" mode="multiSelector" @cancel="onCancel" :value="tempValue" @change="onRangeChange" @columnchange="onColumnChange">
    <slot></slot>
  </picker>
</template>
<script setup>
import { Picker } from '@tarojs/components';
import { useUnload } from '@tarojs/taro';
import { computed, ref, watch } from 'vue';

const props = defineProps({
  range: {
    type: Array,
    default: () => []
  },
  rangeKey: String,
  rangeValue: String,
  layer: {
    type: Number,
    default: 3
  },
  children: {
    type: String,
    default: 'children'
  },
  value: {
    type: Array,
    default: () => []
  }
});

const emit = defineEmits(['change', 'update:value', 'cancel']);

const tempValue = ref(null);

const getValue = (item, idx) => {
  if (props.rangeValue) {
    return item[props.rangeValue];
  }
  return idx;
};
const getName = item => {
  if (!item) return '';
  if (props.rangeKey) {
    return item[props.rangeKey];
  }
  return item;
};
const getChildren = (range, index) => {
  const children = range[index];
  if (!children) {
    return [];
  }
  if (props.children) {
    return children[props.children] ?? [];
  }
  return children;
};

// 按层级展开
const toWrap = (indexs = []) => {
  let newRange = [];
  let range = props.range ?? [];
  for (let i = 0; i < props.layer; i++) {
    newRange.push(range);
    const index = indexs[i] ?? 0;
    range = getChildren(range, index);
  }
  return newRange;
};

const getIndexs = (values, def = -1) => {
  const indexs = [];
  let range = props.range ?? [];
  for (let i = 0; i < props.layer; i++) {
    const value = values[i];
    let index = range.findIndex((a, idx) => getValue(a, idx) == value);
    if (index <= def) {
      index = def;
    }
    range = getChildren(range, index);
    indexs.push(index);
  }
  return indexs;
};

const getValues = (indexs = []) => {
  const values = [];
  let range = props.range ?? [];
  for (let i = 0; i < props.layer; i++) {
    const index = indexs[i];
    values.push(getValue(range[index], index));
    range = getChildren(range, index);
  }
  return values;
};

const getNames = (indexs = []) => {
  const names = [];
  let range = props.range ?? [];
  for (let i = 0; i < props.layer; i++) {
    const index = indexs[i];
    names.push(getName(range[index]));
    range = getChildren(range, index);
  }
  return names;
};

const newRange = computed(() => toWrap(tempValue.value));

const onColumnChange = e => {
  const { column, value: v } = e.detail;
  tempValue.value[column] = v;
};

const onRangeChange = e => {
  const values = getValues(e.detail.value);
  emit('update:value', values);
  emit('change', values);
};

const onCancel = e => {
  tempValue.value = getIndexs(props.value ?? [], 0);
  emit('cancel', e);
};

const unwatch = watch(
  () => props.value,
  () => {
    tempValue.value = getIndexs(props.value ?? [], 0);
  },
  {
    deep: true,
    immediate: true
  }
);

useUnload(() => {
  unwatch();
});

defineExpose({
  isEmpty() {
    const indexs = getIndexs(props.value ?? []);
    return indexs.every(a => a < 0);
  },
  getNames() {
    return getNames(getIndexs(props.value ?? []));
  }
});
</script>
